#pragma
#include <iostream>
#include <vector>
#include <semaphore.h>//信号量头文件
const static int defaultNum=5;//默认容量大小
template<class T>
class RingQueue
{
    private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);//--
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);//++
    }
    void lock(pthread_mutex_t &mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void unlock(pthread_mutex_t& mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
    private:
    std::vector<T> ringqueue_;//存放数据的容器
    int Maxcapa_;
    int c_step;//消费者下标（通过唯一下标访问唯一资源）
    int p_step;//生产者下标
    sem_t space_sem_p;//生产者申请的信号量，代表是否有空间
    sem_t data_sem_c;//消费者申请的信号量，代表是否有数据
    pthread_mutex_t mutex_p;//生产者的锁
    pthread_mutex_t mutex_c;//消费者的锁
    public:
    RingQueue(int defaultcap=defaultNum)
    :ringqueue_(defaultcap),Maxcapa_(defaultcap),c_step(0),p_step(0)//生产消费者初始下标都为0
    {
        //构造初始化信号量
        sem_init(&space_sem_p,0,defaultcap);//生产者一开始的空间资源数目为默认容量大小
        sem_init(&data_sem_c,0,0);//消费者一开始资源数目默认为0

        //初始化锁
        pthread_mutex_init(&mutex_p,nullptr);
        pthread_mutex_init(&mutex_c,nullptr);

    }

    void push(const T& data)
    {
        P(space_sem_p);//申请信号量 p操作 --
        //对共享资源的操作
        lock(mutex_p);//上锁，避免多个个线程时多个生产者同时进来访问
        ringqueue_[p_step]=data;
         p_step++;
        p_step%=Maxcapa_;
        unlock(mutex_p);
        V(data_sem_c);//发布信号量 v操作 ++
       
    }

    void pop(T* out)
    {
        P(data_sem_c);
        lock(mutex_c);//给消费者上锁，避免同时多个消费者进来
        *out=ringqueue_[c_step];
         c_step++;
        c_step%=Maxcapa_;
        unlock(mutex_c);
        V(space_sem_p);
       
    }
    ~RingQueue()
    {
        sem_destroy(&space_sem_p);
        sem_destroy(&data_sem_c);//销毁信号量

        //锁的销毁
        pthread_mutex_destroy(&mutex_c);
        pthread_mutex_destroy(&mutex_p);

    }

};